package com.github.hanlyjiang.androidtemplate.opengl.airhockey;

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;

import com.github.hanlyjiang.androidtemplate.R;
import com.github.hanlyjiang.androidtemplate.opengl.util.LoggerConfig;
import com.github.hanlyjiang.androidtemplate.opengl.util.ShaderHelper;
import com.github.hanlyjiang.androidtemplate.opengl.util.TextResourceReader;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_LINES;
import static android.opengl.GLES20.GL_POINTS;
import static android.opengl.GLES20.GL_TRIANGLES;
import static android.opengl.GLES20.GL_TRIANGLE_FAN;
import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.GLES20.glEnableVertexAttribArray;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glLineWidth;
import static android.opengl.GLES20.glUniform4f;
import static android.opengl.GLES20.glUniformMatrix4fv;
import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glVertexAttribPointer;
import static android.opengl.GLES20.glViewport;
import static android.opengl.Matrix.orthoM;

/**
 * Created by HanlyJiang on 2016/11/26.
 */
public class AirHockeyRender implements GLSurfaceView.Renderer {


    private static final int POSITION_COMPONENT_COUNT = 4;
    private static final int BYTES_PRE_FLOAT = 4;
    private FloatBuffer vertexData;
    private Context context;

    private int program;

    private static final String U_COLOR = "u_Color";
    private int uColorLocation;
    private static final String A_COLOR = "a_Color";
    private int aColorLocation;

    private static final int COLOR_COMPONENT_COUNT = 3;
    private static final int STRIDE =
            (POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PRE_FLOAT;

    private static final String A_POSITION = "a_Position";
    private int aPositionLocation;

    private static final String U_MATRIX = "u_Matrix";
    private final float[] projectionMatrix = new float[16];
    private int uMatrixLocation;



    public AirHockeyRender(Context context) {
        this.context = context;
        // 使用两个三角形表示桌子
        float[] tableVertices = {
                // X Y Z W, R G　B  W值越大，距离屏幕越远
                0f, 0f, 0f, 1.5f, 1f, 1f, 1f,
                -0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
                0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,
                0.5f, 0.8f, 0f, 2f, 0.7f, 0.7f, 0.7f,
                -0.5f, 0.8f, 0f, 2f, 0.7f, 0.7f, 0.7f,
                -0.5f, -0.8f, 0f, 1f, 0.7f, 0.7f, 0.7f,


                // center line
                -0.5f, 0f, 0f, 1.5f, 1f, 0f, 0f,
                0.5f, 0f, 0f, 1.5f, 1f, 0f, 0f,

                // 棒槌
                0f, -0.4f, 0f, 1.25f, 0f, 0f, 1f,
                0f, 0.4f, 0f, 1.75f, 1f, 0f, 0f, // 第二个棒槌是blue的

                // ball
                0f, 0f, 0f, 1.5f, 0f, 1f, 0f,

                // 边框， 两个三角形 red
                -0.52f, -0.82f, 0f, 1f, 1f, 0f, 0f,
                0.52f, 0.82f, 0f, 2f, 1f, 0f, 0f,
                -0.52f, 0.82f, 0f, 2f, 1f, 0f, 0f,
                -0.52f, -0.82f, 0f, 1f, 1f, 0f, 0f,
                0.52f, -0.82f, 0f, 1f, 1f, 0f, 0f,
                0.52f, 0.82f, 0f, 2f, 1f, 0f, 0f,

        };
//        vertexData = ByteBuffer.allocate(tableVertices.length * BYTES_PRE_FLOAT)   // 使用这个会报错： Must use a native order direct Buffer
        vertexData = ByteBuffer.allocateDirect(tableVertices.length * BYTES_PRE_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexData.put(tableVertices);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES20.glClearColor(0.0f,0.0f,0.0f,0.0f);
        String vertexShaderSource = TextResourceReader
                .readTextFileFromResource(context, R.raw.simple_vertext_shader);
        String fragmentShaderSource = TextResourceReader
                .readTextFileFromResource(context, R.raw.simple_fragment_shader);
        // 编译着色器
        int vertexShader = ShaderHelper.compileVertexShader(vertexShaderSource);
        int fragmentShader = ShaderHelper.compileFragmentShader(fragmentShaderSource);

        // 链接着色器
        program = ShaderHelper.linkProgram(vertexShader,fragmentShader);

        if (LoggerConfig.ON) {
            ShaderHelper.validateProgram(program);
        }

        glUseProgram(program);

//        uColorLocation = glGetUniformLocation(program,U_COLOR);
        aColorLocation = glGetAttribLocation(program,A_COLOR);
        aPositionLocation = glGetAttribLocation(program,A_POSITION);
        uMatrixLocation = glGetUniformLocation(program, U_MATRIX);

        // 顶点
        vertexData.position(0);
        glVertexAttribPointer(aPositionLocation,POSITION_COMPONENT_COUNT,GL_FLOAT,
                false,STRIDE,vertexData);
        glEnableVertexAttribArray(aPositionLocation);

        // 顶点颜色
        vertexData.position(POSITION_COMPONENT_COUNT); // 移动到颜色
        glVertexAttribPointer(aColorLocation,COLOR_COMPONENT_COUNT,GL_FLOAT,
                false,STRIDE,vertexData); // STRIDE 告诉OpenGL 每个颜色之间有多少个字节
        glEnableVertexAttribArray(aColorLocation);

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        glViewport(0, 0, width, height);
        final float aspectRatio = width > height ?
                (float) width / (float)height:
                (float) height / (float) width;
        float scale = 1f;
        if(width > height){
            // landscape
            orthoM(projectionMatrix,0 , - aspectRatio*scale, aspectRatio*scale,
                    -1*scale, 1f*scale, -1f*scale, 1f*scale);
//            orthoM(projectionMatrix,0 , - aspectRatio, aspectRatio, -1, 1f, -1f, 1f);
        }else{
//            orthoM(projectionMatrix, 0 , -1f, 1f, -aspectRatio, aspectRatio, -1f, 1f);
            orthoM(projectionMatrix, 0 , -1f*scale, 1f*scale, -aspectRatio*scale,
                    aspectRatio*scale, -1f*scale, 1f*scale);
        }
    }

    @Override
    public void onDrawFrame(GL10 gl) {

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        // Sending the Matrix to the Shader
        glUniformMatrix4fv(uMatrixLocation, 1, false, projectionMatrix, 0);

        // 绘制外部边框更新u_Color 的值
        glUniform4f(uColorLocation,0f,1f,0f,1.0f);
        // 从vertex的第0个开始读取，总共读入6个
        glDrawArrays(GL_TRIANGLES,11,6);

        // 更新u_Color 的值
//        glUniform4f(uColorLocation,1.0f,1.0f,1.0f,1.0f);
        // 从vertex的第0个开始读取，总共读入6个
        glDrawArrays(GL_TRIANGLE_FAN,0,6);

        // Draw center line
        glUniform4f(uColorLocation,1.0f,0f,0f,1f);
        glLineWidth(18f);
        glDrawArrays(GL_LINES,6,2);

        // draw mallets
        glUniform4f(uColorLocation,1.0f,0.0f,0.0f,1.0f);
        glDrawArrays(GL_POINTS,8,1);

        glUniform4f(uColorLocation,0.0f,0.0f,1.0f,1.0f);
        glDrawArrays(GL_POINTS,9,1);

        glUniform4f(uColorLocation,0f,1f,0f,1f);
        glDrawArrays(GL_POINTS,10,1);

//        glUniform4f(uColorLocation,1f,0f,0f,1f);
//        glLineWidth(18f);
//        glDrawArrays(GL_LINES,0,6);

    }
}
